package com.weipu.common.util;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Environment;
import android.util.Log;

/**
 * 日志管理公共类
 * 开启日志后需要可以通过adb shell方式打开对应级别日志，详见 TAG描述
 *
 * @author hjd008
 * @version [版本号, 2012-9-17]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class Logger {
    /**
     * 默认日志TAG
     * 日志开启方式: adb shell setprop log.tag.WEIPU_ANDROID DEBUG
     * 注: adb shell setprpo：设置属性值
     * log.tag.WEIPU_ANDROID: 需要设置属性名
     * DEBUG:W上述属性值
     */
    private static final String TAG = "WEIPU_ANDROID";

    /**
     * 是否允许debug日志
     */
    public static boolean isLog = true;

    /**
     * 是否允许写入SD卡
     */
    private static final boolean WRITE_SDCARD_LOG = true;

    /**
     * 更新日志开关
     *
     * @param enable
     */
    public static void updateLogEnable(boolean enable) {
        Logger.isLog = enable;
    }

    /**
     * 时间格式
     */
    private static final String COMMON_DATE = "yyyy-MM-dd HH:mm:ss";

    /**
     * 异常日志大小限制在5M
     */
    private static final float ERR_LOG_SIZE = 5 * 1024 * 1024.0f;

    private Logger() {
    }

    private static String buildMsg(String msg) {

        StringBuilder buffer = new StringBuilder();
        Date date = new Date();
        String time = new SimpleDateFormat(COMMON_DATE).format(date);

        buffer.append(time);
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        buffer.append(" [");
        buffer.append(Thread.currentThread().getName());
        buffer.append(":");
        buffer.append(stackTraceElement.getFileName());
        buffer.append(":");
        buffer.append(stackTraceElement.getLineNumber());
        buffer.append(":");
        buffer.append(stackTraceElement.getMethodName());
        buffer.append("()] ");
        buffer.append(msg);
        buffer.append("\n");
        return buffer.toString();
    }

    public static void v(String msg) {
        if (isLog || Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, buildMsg(msg));
        }
    }

    public static void v(String tag, String msg) {
        if (isLog || Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(tag, buildMsg(msg));
        }
    }

    public static void d(String msg) {
        if (isLog || Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, buildMsg(msg));
        }
    }

    public static void d(String tag, String msg) {
        if (isLog || Log.isLoggable(TAG, Log.DEBUG)) {

            Log.d(tag, buildMsg(msg));
        }
    }

    public static void i(String msg) {
        if (isLog || Log.isLoggable(TAG, Log.INFO)) {
            Log.i(TAG, buildMsg(msg));
        }
    }

    public static void i(String tag, String msg) {
        if (isLog || Log.isLoggable(TAG, Log.INFO)) {
            Log.i(tag, buildMsg(msg));
        }
    }

    public static void w(String msg) {
        if (isLog || Log.isLoggable(TAG, Log.WARN)) {
            String info = buildMsg(msg);
            Log.w(TAG, info);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info);
            }
        }
    }

    public static void w(String tag, String msg) {
        if (isLog || Log.isLoggable(TAG, Log.WARN)) {
            String info = buildMsg(msg);
            Log.w(tag, info);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info);
            }
        }
    }

    public static void w(String msg, Exception e) {
        if (isLog || Log.isLoggable(TAG, Log.WARN)) {
            String info = buildMsg(msg);
            Log.w(TAG, info, e);

            if (WRITE_SDCARD_LOG || null != e) {
                writeFileToSD(info + Common.getStackTrace(e));
            }
        }
    }

    public static void w(String tag, String msg, Exception e) {
        if (isLog || Log.isLoggable(TAG, Log.WARN)) {
            String info = buildMsg(msg);
            Log.w(tag, info, e);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info + Common.getStackTrace(e));
            }
        }
    }

    public static void e(String msg) {
        if (isLog || Log.isLoggable(TAG, Log.ERROR)) {
            String info = buildMsg(msg);
            Log.e(TAG, info);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info);
            }
        }
    }

    public static void e(String tag, String msg) {
        if (isLog || Log.isLoggable(TAG, Log.ERROR)) {
            String info = buildMsg(msg);
            Log.e(tag, info);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info);
            }
        }
    }

    public static void e(String msg, Exception e) {
        if (isLog || Log.isLoggable(TAG, Log.ERROR)) {
            String info = buildMsg(msg);
            Log.e(TAG, info, e);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info + Common.getStackTrace(e));
            }
        }
    }

    public static void e(String tag, String msg, Exception e) {
        if (isLog || Log.isLoggable(TAG, Log.ERROR)) {
            String info = buildMsg(msg);
            Log.e(tag, info, e);

            if (WRITE_SDCARD_LOG) {
                writeFileToSD(info + Common.getStackTrace(e));
            }
        }
    }

    private static void writeFileToSD(String context) {
        RandomAccessFile raf = null;
        String sdStatus = Environment.getExternalStorageState();
        if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) {
            Log.d(TAG, "SD card is not avaiable right now.");
            return;
        }
        try {
            String pathName = Environment.getExternalStorageDirectory().getPath() + "/dxloghome/"; /* "/sdcard/dxloghome/"; */
            String fileName = "error.log";
            File path = new File(pathName);
            File file = new File(pathName + fileName);
            if (!path.exists()) {
                Log.d(TAG, "Create the path:" + pathName);
                path.mkdir();
            }
            if (!file.exists()) {
                Log.d(TAG, "Create the file:" + fileName);
                file.createNewFile();
            }

            raf = new RandomAccessFile(file, "rw");
            if (file.length() > ERR_LOG_SIZE) {
                raf.seek(0);
            } else {
                raf.seek(file.length());
            }

            raf.write(context.getBytes());
        } catch (Exception e) {
            Log.e(TAG, "Error to write SD card.");
        } finally {
            if (null != raf) {
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
